
import javax.crypto.*;
import javax.crypto.spec.*;

/**
 * This program generates a AES key, retrieves its raw bytes, and
 * then reinstantiates a AES key from the key bytes.
 * The reinstantiated key is used to initialize a AES cipher for
 * encryption and decryption.
 */
public class AES {

    /**
     * Turns array of bytes into string
     * Credit:  this method is unchanged from an example on the Sun website
     * @param buf	Array of bytes to convert to hex string
     * @return	Generated hex string
     */
    public static String asHex(byte buf[]) {
        StringBuffer strbuf = new StringBuffer(buf.length * 2);
        int i;

        for (i = 0; i < buf.length; i++) {
            if (((int) buf[i] & 0xff) < 0x10) {
                strbuf.append("0");
            }
            strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
        }
        return strbuf.toString();
    }

    public static void main(String[] args) throws Exception {

        // Get the KeyGenerator
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        // Generate the secret key specs.
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        
        // Instantiate the cipher
        Cipher cipher = Cipher.getInstance("AES");

        System.out.println("\n** ENCRYPT **\n");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encryptedBytes = cipher.doFinal((args.length == 0 ? "This is just an example" : args[0]).getBytes());
        System.out.println("\toriginal from command line: \n" + args[0]);
        System.out.println("\tencrypted hex string: \n" + asHex(encryptedBytes));
        System.out.println("\tencrypted binary: \n"+ convertBytesToBinaryString(encryptedBytes));
        
        System.out.println("\n** DECRYPT **\n");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        System.out.println("\tdecrypted bytes to string: \n" + new String(decryptedBytes));
        System.out.println("\tdecrypted bytes to binary string: \n" + convertBytesToBinaryString(decryptedBytes));
        System.out.println("");
    }

    public static String convertBytesToBinaryString(byte[] bytes) {
        boolean[][] binary = convertBytesToBits(bytes);
        String temp = "";
        for (int j = 0; j < bytes.length; j++) {
            for (int i = 7; i >= 0; i--) {
                if (binary[j][i]) {
                    temp = temp.concat("1");
                } else {
                    temp = temp.concat("0");
                }
            }
            //System.out.print(temp);
            //temp = "";
        }
        return temp;
    }

    public static boolean[][] convertBytesToBits(byte[] b) {
        boolean[][] bytes = new boolean[b.length][];
        boolean[] bits = null;

        for (int j = 0; j < b.length; j++) {
            bits = new boolean[8];
            for (int i = 0; i < bits.length; i++) {
                bits[i] = ((b[j] & (1 << i)) != 0);
            }
            bytes[j] = bits;
        }
        return bytes;
    }
}
